package com.ang.mybatisplus.base.controller;


import com.ang.mybatisplus.base.entity.User;
import com.ang.mybatisplus.base.service.UserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author ssang
 * @since 2021-05-10
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    UserService userService;

    @Autowired
    private PlatformTransactionManager platformTransactionManager;

    @Autowired
    private TransactionDefinition transactionDefinition;

    @RequestMapping("/list")
    public List list(){
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("id",1);
        wrapper.eq("name", "张三");
        List list = userService.list(wrapper);

        System.out.println(Thread.currentThread().getName());

        return list;
    }

    @RequestMapping("/listUser")
    public List listUser(){
        User user = new User();
        user.setId(1);
        user.setName("张三");
        QueryWrapper wrapper = new QueryWrapper(user);
        List list = userService.list(wrapper);

        System.out.println(Thread.currentThread().getName());

        return list;
    }

    /**
     * 添加，测试自动填充create_time
     */
    @GetMapping("/addFill")
    public String addFill(){
        User user = new User();
        user.setName("张三");
        user.setAge(15);
        userService.save(user);

        return "success";
    }

    /**
     * 修改，测试自动填充update_time
     */
    @GetMapping("/updateFill")
    public String updateFill(){
        User user = userService.getById("1");

        userService.updateById(user);

        return "success";
    }

    @RequestMapping("/updateByWrapper")
    public String updateByWrapper(){
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.eq("id",2);
        updateWrapper.set("name","张三");

        userService.update(null, updateWrapper);

        return "success";
    }

    /**
     * user和updateWrapper都设置name，以updateWrapper为主
     * @return
     */
    @RequestMapping("/updateByWrapperUser")
    public String updateByWrapperUser(){
        User user = new User();
        user.setName("李四");

        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.eq("id",2);
//        updateWrapper.set("name","张三");

        userService.update(user, updateWrapper);

        return "success";
    }

    /**
     * 测试mybatis-plus分页插件功能，普通分页
     */
    @GetMapping("/listPage")
    public List listPage(){
        List<User> list = new ArrayList<>();

        //参数：当前页，查询数量，是否返回总数
        Page<User> page = new Page<>(1,2,true);
        IPage<User> iPage = userService.getUserPage(page, new QueryWrapper());
        list = iPage.getRecords();

        return list;
    }

    /**
     * 测试分页插件，xml接口添加分页
     */
    @GetMapping("/listPageXml")
    public List listPageXml(){
        List<User> list = new ArrayList<>();

        //构建查询条件
        User user = new User();
        user.setAge(1);
        //参数：当前页，查询数量，是否返回总数
        Page<User> page = new Page<>(1,2,true);
        //page要放在第一位
        IPage<User> iPage = userService.getUserPageXml(page, user);
        list = iPage.getRecords();

        return list;
    }

    /**
     * 测试分页插件，Lambda表达式
     */
    @GetMapping("/listPageLambda")
    public List<User> listPageLambda(){
        List<User> list = new ArrayList<>();

        //userService.getBaseMapper() 就是 userMapper
        //需要用泛型，User
        LambdaQueryChainWrapper<User> lambdaQueryChainWrapper = new LambdaQueryChainWrapper(userService.getBaseMapper());

        //list = lambdaQueryChainWrapper.gt(User::getAge,1).list();
        Page<User> page = new Page<>(1,2);
        IPage<User> iPage = lambdaQueryChainWrapper.gt(User::getAge, 1).page(page);

        list = iPage.getRecords();

        return list;
    }

    /**
     * 测试拦截器，数据脱敏，查询参数加密
     * 参数为User，并对对象使用@Param注解
     */
    @RequestMapping("/listUserSensitiveCryptParam")
    public List<User> listUserSensitiveCryptParam(){
        User user = new User();
        user.setName("张三");
        return userService.listByUserParam(user);
    }

    /**
     * 测试拦截器，数据脱敏，查询参数加密
     * 参数为User，并对字符串使用@Param注解
     */
    @RequestMapping("/listUserSensitiveCryptParamStr")
    public List<User> listUserSensitiveCryptParamStr(){
        return userService.listByNameParam("张三");
    }

    /**
     * 测试拦截器，数据脱敏，查询参数加密
     * 参数为User，不使用@Param注解
     */
    @RequestMapping("/listUserSensitiveNoParam")
    public List<User> listUserSensitiveNoParam(){
        User user = new User();
        user.setName("张三");
        return userService.listByUserNoParam(user);
    }

    /**
     * 测试拦截器，数据脱敏，参数为Map
     */
    @RequestMapping("/listUserSensitiveMap")
    public List<User> listUserSensitiveMap(){
        Map map = new HashMap();
        map.put("name","张三");
        map.put("age",1);
        return userService.listUserByMap(map);
    }

    /**
     * jmeter，创建100个线程
     * 1.开启事务
     * 2.线程执行update操作（会触发行锁）
     * 3.线程包含10，开始睡眠60s
     * 4.其他线程继续执行，在执行update时，会等待
     * 5.超过等待时间，报错  Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded;
     * 6.sql执行： select * from information_schema.innodb_trx;可以查看到等待锁的线程；    trx-state:LOCK WAIT
     * @return
     * @throws Exception
     */
    @PostMapping("/update")
    public String update() throws Exception{
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("id",1);
        User user = userService.getOne(wrapper);

        //手动开启事务
        TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);

        int age = Integer.valueOf(10);
        user.setAge(age);
        userService.updateById(user);

        //http-nio-8090-exec-10
        String threadName = Thread.currentThread().getName();

        if(threadName.indexOf("-10") > -1){
            //睡眠，暂时不提交事务
            System.out.println(threadName);
            Thread.sleep(60000);
            System.out.println("==========线程睡眠结束==========");
        }

        //手动提交事务
        platformTransactionManager.commit(transaction);

        return "success";
    }
}
